/**
	Copyright (c) 2010 ATTi 
	All rights reserved.
	Author: Michael Shu,
	Date: 10/7/2010 
*/

public without sharing class AASFieldUpdateHelperClass {
	
	/*
	   AD-24230, Quote status update, updated by Paul Lo, 10/12/11:
	   
	   RFP Draft -> Quote Draft
      RFP Submitted -> Quote Requested
      Proposal Submitted -> Quote Returned
      
      AD-28117, update Opportunity stage names, in parenthesis is what it is today, 02/16/2012:
      * 10 Ascertainment by AE (10/Ascertainment)
      * 25 Proposal Requested by AE (25/Quote Required/Requested) 
      * 25 Proposal Returned to AE (35/Proposal provided to Sales)
      * 50 Strong Buying Signals, Likely to Close (50/Proposal sent to client)

	*/
	public static final String OPP_STAGE_25 = 'Proposal Requested by AE';
	
	private static Set<ID> accountAASRecordTypeID;
	private static Set<ID> opportunityAASRecordTypeID;
	private static Set<ID> leadAASRecordTypeID;
	private static Set<ID> AASAgencyAccountIds = new Set<ID>();
	public static String User_Prefix  =  GeneralConstants.User_Prefix;
	public static Boolean isUserUpdate = true;
	public static Boolean isNotUserUpdate = false;
	public static String Proposal_Submitted = 'Quote Returned';
	public static String RFP_Submitted = 'Quote Requested';
	public static String New_Opp_Stage = 'Proposal Returned to AE'; // 25%
	public static String Proposal_Sent_To_Client = 'Strong Buying Signals, Likely to Close';
	public static Boolean hasNOTUpdateOpportnityWithAccount = true; 
	public static String AAS_Agency_Account_RT_NAME = 'AAS Agency';
	public static String AAS_Master_Client_RT_NAME = 'AAS Master Client';
	public static set<String> RT_AAS_ACCOUNT = GeneralConstants.RT_AAS_ACCOUNT;
	public static set<String> RT_AAS_LEAD = GeneralConstants.RT_AAS_LEAD;
	public static set<String> RT_AAS_OPPORTUNITY = GeneralConstants.RT_AAS_OPPORTUNITY;
	public static Boolean isAgencyUpdated = false;
	public static Boolean AFTER = true;
		
	public static Set<ID> getAccountAASRecordTypeID(){
		if(accountAASRecordTypeID == null){
			accountAASRecordTypeID = new Set<ID>();
			for(String s : RT_AAS_ACCOUNT){
				ID temp = RecordTypeHelper.GetRecordTypeID('Account',  s);
				accountAASRecordTypeID.add(temp);
			}
		}
		return accountAASRecordTypeID;
	}
	
	public static Set<ID> getOpportunityAASRecordTypeID(){
		if(opportunityAASRecordTypeID == null){
			opportunityAASRecordTypeID = new Set<ID>();
			for(String s : RT_AAS_OPPORTUNITY){
				ID temp = RecordTypeHelper.GetRecordTypeID('Opportunity',  s);
				opportunityAASRecordTypeID.add(temp);
			}
		}
		return opportunityAASRecordTypeID;
	}
	
	public static Set<ID> getLeadAASRecordTypeID(){
		if(leadAASRecordTypeID == null){
			leadAASRecordTypeID = new Set<ID>();
			for(String s : RT_AAS_LEAD){
				ID temp = RecordTypeHelper.GetRecordTypeID('Lead',  s);
				leadAASRecordTypeID.add(temp);
			}
		}
		return leadAASRecordTypeID;
	}
	
	private static void updateOppsWithAccounts(List<Account> accounts, Map<ID, Account> triggerMap){
		if(hasNOTUpdateOpportnityWithAccount){
			Map<ID, Account> acctMaps = new Map<ID, Account>();
			for(Account a : accounts){
				if(a.Id != null){
					acctMaps.put(a.Id, a);
				}
			}
			if(!acctMaps.isEmpty() && triggerMap != null){
				List<Opportunity> opps = [select ID, OwnerId, AccountId from Opportunity where AccountId IN: acctMaps.keySet() and IsClosed =: false];
				List<Opportunity> opps_update = new List<Opportunity>();
				for(Opportunity o : opps){
					Account oldAcct = triggerMap.get(o.AccountId);
					Account a = acctMaps.get(o.AccountId);
					if(o.OwnerId == oldAcct.OwnerId && o.OwnerId != a.OwnerId){
						o.OwnerId = a.OwnerId; // to fire the opportunity trigger
						opps_update.add(o);
					}
				}
				if(!opps_update.isEmpty()){
					update opps_update;
					hasNOTUpdateOpportnityWithAccount = false;
				}
			}
		}
	}

	public static void updateAASAccountfieldsInBeforeEvent(List<Account> accounts, Set<ID> ownerIds, Map<ID, Account> triggerOldMap){
		Map<ID, User> users = getUserInfo(ownerIds);
		updateAccts(accounts, users, isNotUserUpdate);
		updateOppsWithAccounts(accounts, triggerOldMap);
	}

	public static void updateAASOpportunityfieldsInBeforeEvent(List<Opportunity> opportunities){
		Set<ID> ownerIds = new Set<ID>();
		for(Opportunity o : opportunities){
			ownerIds.add(o.OwnerId);
		}
		Map<ID, User> users = getUserInfo(ownerIds);
		updateOpps(opportunities, users, isNotUserUpdate);
	}

	public static void updateAASLeadfields(List<Lead> leads, Set<ID> ownerIds){
		Map<ID, User> users = getUserInfo(ownerIds);
		updateLeads(leads, users, isNotUserUpdate);
	}

	public static void updateAASQuotefieldsInInsert(List<Quote> quotes){
		Set<ID> oppIds = new Set<ID>();
		for(Quote q : quotes){
			oppIds.add(q.OpportunityId);
		}
		Map<ID, Opportunity> opps = new Map<ID, Opportunity>([select Pre_Sale_Manager__c, Post_Sale_Manager__c from Opportunity where ID IN : oppIds and RecordType.Name IN: RT_AAS_OPPORTUNITY]);
		if(!opps.isEmpty()){
			for(Quote q : quotes){
				if(opps.containsKey(q.OpportunityId)){
					q.Pre_Sale_Manager__c  = opps.get(q.OpportunityId).Pre_Sale_Manager__c;
					q.Post_Sale_Manager__c = opps.get(q.OpportunityId).Post_Sale_Manager__c;
				}
			}			
		}
	}
	
	public static void updateAASQuotefieldsFromOpps(map<ID, ID> oppAndOwnerIds, map<ID, User> users){	
		List<Quote> quotes = [select OpportunityId, Pre_Sale_Manager__c, Post_Sale_Manager__c from Quote 
		                      where OpportunityId IN : oppAndOwnerIds.keySet()];
		if(!quotes.isEmpty()){
			List<Quote> quotes_to_update = new List<Quote>();
			for(Quote q : quotes){
				ID oppOwnerId = oppAndOwnerIds.get(q.OpportunityId);
				User u = users.get(oppOwnerId);
				if(u != null){
					if(u.Pre_Sale_Manager__c != q.Pre_Sale_Manager__c || u.Post_Sale_Manager__c != q.Post_Sale_Manager__c){
						q.Pre_Sale_Manager__c = u.Pre_Sale_Manager__c;
						q.Post_Sale_Manager__c = u.Post_Sale_Manager__c;
						quotes_to_update.add(q);
					}
				}
			}
			if(!quotes_to_update.isEmpty()){
				update quotes_to_update;
			}
		}
	}
		
	private static Map<ID, User> getUserInfo(Set<ID> ownerIds){
		return new Map<ID, User>([select ID, Pre_Sale_Manager__c, Post_Sale_Manager__c, Office__c, Sales_Region__c from User where ID IN: ownerIds]);
	} 
	
	public static void updateAccts(List<Account> accts, Map<ID, User> users, Boolean is_u_update){
		if(!accts.isEmpty()){
			List<Account> accts_udpate = new List<Account>();
			for(Account a : accts){
				User u = users.get(a.OwnerId); 
				if(u != null){
					if(a.Pre_Sale_Manager__c != u.Pre_Sale_Manager__c || a.Post_Sale_Manager__c != u.Post_Sale_Manager__c || a.Office__c != u.Office__c || a.Sales_Region__c != u.Sales_Region__c){
						a.Pre_Sale_Manager__c = u.Pre_Sale_Manager__c;
						a.Post_Sale_Manager__c = u.Post_Sale_Manager__c;
						a.Office__c = u.Office__c;
						a.Sales_Region__c = u.Sales_Region__c;
						accts_udpate.add(a);
					}
				}
			}
			if(is_u_update && !accts_udpate.isEmpty()){
				update accts_udpate;
			}
		}
	}	
			
	public static void updateOpps(List<Opportunity> opps, Map<ID, User> users, Boolean is_u_update){
		if(!opps.isEmpty()){
			List<Opportunity> opps_udpate = new List<Opportunity>();
			map<ID, ID> oppsOwnerIdmap = new map<ID, ID>();
			for(Opportunity o : opps){
				oppsOwnerIdmap.put(o.Id, o.OwnerId);
				User u = users.get(o.OwnerId); 
				if(u != null){
					if(o.Pre_Sale_Manager__c != u.Pre_Sale_Manager__c || o.Post_Sale_Manager__c != u.Post_Sale_Manager__c || o.Office__c != u.Office__c || o.Sales_Region__c != u.Sales_Region__c){
						o.Pre_Sale_Manager__c = u.Pre_Sale_Manager__c;
						o.Post_Sale_Manager__c = u.Post_Sale_Manager__c;
						o.Office__c = u.Office__c;
						o.Sales_Region__c = u.Sales_Region__c;
						opps_udpate.add(o);
					}
				}
			}
			updateAASQuotefieldsFromOpps(oppsOwnerIdmap, users);
			if(is_u_update && !opps_udpate.isEmpty()){
				update opps_udpate;
			}		
		}
	}

	public static void updateLeads(List<Lead> leads, Map<ID, User> users, Boolean is_u_update){	
		if(!leads.isEmpty()){
			List<Lead> leads_udpate = new List<Lead>();
			for(Lead l : leads){
				User u = users.get(l.OwnerId); 
				if(u != null){
					if(l.Office__c != u.Office__c || l.Sales_Region__c != u.Sales_Region__c 
					|| l.Office_To_Opp__c != u.Office__c || l.Sales_Region_To_Opp__c != u.Sales_Region__c 
					|| l.Pre_Sale_Manager_To_Acc__c != u.Pre_Sale_Manager__c || l.Post_Sale_Manager_To_Acc__c != u.Post_Sale_Manager__c){
						l.Office__c = u.Office__c;
						l.Sales_Region__c = u.Sales_Region__c;
						//--------For lead field mapping------
						l.Office_To_Opp__c = u.Office__c;
						l.Sales_Region_To_Opp__c = u.Sales_Region__c;
						l.Pre_Sale_Manager_To_Acc__c = u.Pre_Sale_Manager__c;
						l.Pre_Sale_Manager_To_Opp__c = u.Pre_Sale_Manager__c;
						l.Post_Sale_Manager_To_Acc__c = u.Post_Sale_Manager__c;
						l.Post_Sale_Manager_To_Opp__c = u.Post_Sale_Manager__c;
						//------------------------------------
						leads_udpate.add(l);
					}
				}
			}
			if(is_u_update && !leads_udpate.isEmpty()){
				update leads_udpate;
			}		
		}
	}	
	
	public static void updateAASOppsFromQuote(Set<ID> oppIds_proposal, Set<ID> oppIds_rfp){
		Set<ID> AASOppRecordTypeID = getOpportunityAASRecordTypeID();
		List<Opportunity> oppAAS = [select ID, Quote_Provided_To_Sales_Date__c, Quote_Request_Date__c from Opportunity where (ID IN: oppIds_proposal Or ID IN: oppIds_rfp) and RecordTypeId IN: AASOppRecordTypeID];
		if(!oppAAS.isEmpty()){
			for(Opportunity o : oppAAS){
				if(oppIds_proposal.contains(o.ID) && o.Quote_Provided_To_Sales_Date__c == null){
					o.Quote_Provided_To_Sales_Date__c = Date.today();
					o.StageName = New_Opp_Stage;
				}
				if(oppIds_rfp.contains(o.ID) && o.Quote_Request_Date__c == null){
					o.Quote_Request_Date__c = Date.today();
					
					/* 
					   Ad-24230 AdWorks B-11, updated by Paul Lo, 10/12/11:
					   When the Quote Status is changed to "Quote Requested" (old "RFP Submitted"), update the Opportunity Stage to 25%
					*/
					o.StageName = OPP_STAGE_25;
				}
			}
			update oppAAS;
		}
	}	
	
	public static void setAASOppfields (List<Opportunity> opps){
		Set<ID> AASOppRecordTypeID = getOpportunityAASRecordTypeID();
		for(Opportunity o : opps){
			if(AASOppRecordTypeID.contains(o.RecordTypeId)){
				if(o.StageName == Proposal_Sent_To_Client && o.Proposal_Presented_To_Client__c == null){
					o.Proposal_Presented_To_Client__c = Date.today();
				}
				Date topDate = Date.today().toStartOfMonth();
				Date bottomDate = Date.today().addYears(-1).toStartOfMonth();
				System.debug('Test topDate = ' + topDate + ' bottomDate =  ' + bottomDate);
				if(o.Probability >= 90 && topDate > o.CloseDate && o.CloseDate >= bottomDate){
					o.AAS_Age_Less_Than_12_Months__c = true;
				}else{
					o.AAS_Age_Less_Than_12_Months__c = false;
				}
			}
		}
	}
	
	public static void setAASAgencyAccountIdsInDeleteOrInsert(List<Opportunity> Opps){
		Set<ID> AASOppRecordTypeID = getOpportunityAASRecordTypeID();
		for(Opportunity o : Opps){
			if(AASOppRecordTypeID.contains(o.RecordTypeId) && o.AAS_Agency__c != null && o.AAS_Age_Less_Than_12_Months__c == true && o.Amount > 0){
				AASAgencyAccountIds.add(o.AAS_Agency__c);
			}
			// add master client account record types to the set under the same conditions
			if(AASOppRecordTypeID.contains(o.RecordTypeId) && o.AAS_Master_Client__c != null && o.AAS_Age_Less_Than_12_Months__c == true && o.Amount > 0){
				AASAgencyAccountIds.add(o.AAS_Master_Client__c);
			}
		}
	}

	public static void setAASAgencyAccountIdsInUpdate(List<Opportunity> opps, Map<ID, Opportunity> oldOpps){
		Set<ID> AASOppRecordTypeID = getOpportunityAASRecordTypeID();
		for(Opportunity o : Opps){
			Opportunity old_o = oldOpps.get(o.Id);
			if(AASOppRecordTypeID.contains(o.RecordTypeId)){
				if(o.AAS_Agency__c != null && (old_o.AAS_Age_Less_Than_12_Months__c != o.AAS_Age_Less_Than_12_Months__c || old_o.Amount != o.Amount)){
					AASAgencyAccountIds.add(o.AAS_Agency__c);
				}
				// add master client account record types to the set under the same conditions
				if(o.AAS_Master_Client__c != null && (old_o.AAS_Age_Less_Than_12_Months__c != o.AAS_Age_Less_Than_12_Months__c || old_o.Amount != o.Amount)){
					AASAgencyAccountIds.add(o.AAS_Master_Client__c);
				}
				if(old_o.AAS_Agency__c != o.AAS_Agency__c){
					AASAgencyAccountIds.add(old_o.AAS_Agency__c);
					AASAgencyAccountIds.add(o.AAS_Agency__c);
				}
				if(old_o.AAS_Master_Client__c != o.AAS_Master_Client__c){
					AASAgencyAccountIds.add(old_o.AAS_Master_Client__c);
					AASAgencyAccountIds.add(o.AAS_Master_Client__c);
				}
			}
		}
	}
		

		public static void refresh_Agency_Acct_12_month_sold(){
		if(!isAgencyUpdated && !AASAgencyAccountIds.isEmpty()){
			List<String> Recs = new List<String>{AAS_Agency_Account_RT_NAME, AAS_Master_Client_RT_NAME};
			List<Account> allAccts = new List<Account>([select Id, Agency_12_Months_Sold__c, Client_12_Months_Sold__c, RecordType.Name
			                                                     from Account where Id IN: AASAgencyAccountIds and RecordType.Name IN :Recs]);
			
			Map<ID, Account> agencyAccts = new Map<ID, Account>();
			Map<ID, Account> masterClientAccts = new Map<ID, Account>();
			
			for (Account acc : allAccts) {
				if (acc.RecordType.Name == AAS_Agency_Account_RT_NAME) {
					agencyAccts.put(acc.Id, acc);
				} else {
					masterClientAccts.put(acc.Id, acc);
				}
			}
			
			if(!agencyAccts.isEmpty() || !masterClientAccts.isEmpty()){
				List<Opportunity> AASOpps = [select AAS_Agency__c, AAS_Master_Client__c, Amount from Opportunity where 
										(AAS_Agency__c IN: agencyAccts.keySet() or AAS_Master_Client__c in :masterClientAccts.keySet())
										and RecordType.Name IN: RT_AAS_OPPORTUNITY and AAS_Age_Less_Than_12_Months__c = true and Amount > 0];
				Map<ID, Double> sum = new Map<ID, Double>();
				for(Opportunity o : AASOpps){
					if(sum.containsKey(o.AAS_Agency__c)){
						Double temp = sum.get(o.AAS_Agency__c);
						temp += o.Amount;
						sum.put(o.AAS_Agency__c , temp);
					}else{
						sum.put(o.AAS_Agency__c , o.Amount);
					}
					if(sum.containsKey(o.AAS_Master_Client__c)){
						Double temp = sum.get(o.AAS_Master_Client__c);
						temp += o.Amount;
						sum.put(o.AAS_Master_Client__c , temp);
					}else{
						sum.put(o.AAS_Master_Client__c , o.Amount);
					}
				}
					List<Account> acct_to_update = new List<Account>();
					for(Account acct : agencyAccts.values()){
						if(sum.containsKey(acct.Id)){
							if(acct.Agency_12_Months_Sold__c != sum.get(acct.Id)){
								acct.Agency_12_Months_Sold__c = sum.get(acct.Id);
								acct_to_update.add(acct);
							}
						}else{
								if(acct.Agency_12_Months_Sold__c != 0){
									acct.Agency_12_Months_Sold__c = 0;
									acct_to_update.add(acct);
								}
							}
					}
					for(Account acct : masterClientAccts.values()){
						if(sum.containsKey(acct.Id)){
							if(acct.Client_12_Months_Sold__c != sum.get(acct.Id)){
								acct.Client_12_Months_Sold__c = sum.get(acct.Id);
								acct_to_update.add(acct);
							}
						}else{
								if(acct.Client_12_Months_Sold__c != 0){
									acct.Client_12_Months_Sold__c = 0;
									acct_to_update.add(acct);
								}
							}
					}
				if(!acct_to_update.isEmpty()){
					try{
						update acct_to_update;
						isAgencyUpdated = true;
					}Catch(Exception ex){
						GeneralConstants.mailAnyExceptionToMe('AASFieldUpdateHelperClass', 'update AAS Agency Account amount fail ', ex);
					}
				}
			}
		}
	}
	
	public static void updateAASoppsWithoutChange(Set<ID> acc_ids){
		List<Opportunity> opps = [select id from Opportunity where AccountId IN: acc_ids];
		try{
			update opps;
		}catch(Exception ex){
            GeneralConstants.mailAnyExceptionToMe('AASFieldUpdateHelperClass', 'update opps from Account Fail', ex);					
		}		
	}
	
	public static void stampPOIndexAccountFieldsAndValidateInInsertAndUpdate(List<Opportunity> opps_insert, List<Opportunity> opps_update, Map<ID, Opportunity> oldMap){
		setPOIndexAccountFieldsValues(opps_insert, opps_update,!AFTER);
		checkAllValidationRules(opps_insert, opps_update, oldMap);
	}	
	
	public static void stampPOIndexAccountFieldsInAfterEvent(Set<ID> oppids_after_insert){
		List<Opportunity> opps_insert = [select Id, AccountId, NPO_ID__c, AAS_Agency__c, AAS_Master_Client__c from Opportunity where Id IN: oppids_after_insert];
		List<Opportunity> opps_update = new List<Opportunity>();
		setPOIndexAccountFieldsValues(opps_insert, opps_update,AFTER);
	}
	
	public static void updateNAOIDofFulfillmentOrders(Set<ID> opp_ids){
		if(!opp_ids.isEmpty()){
			List<Order__c> orders = [select id from Order__c where Opportunity__c IN: opp_ids];
			if(!orders.isEmpty()) {update orders;}
		}
	}
	
	private static void checkAllValidationRules(List<Opportunity> opps_insert, List<Opportunity> opps_update, Map<ID, Opportunity> oldMap){
		List<Opportunity> opps;
		if(!opps_insert.isEmpty()){
			opps = opps_insert;
		}else{
			opps = opps_update;
		}
		for(Opportunity o : opps){
			Boolean isChangedOrNew = false;
			if(oldMap != null){
				Opportunity oldOpp = oldMap.get(o.Id);
				isChangedOrNew = o.Contract_Termination_Date__c != oldOpp.Contract_Termination_Date__c || o.Contract_Start_Date__c != oldOpp.Contract_Start_Date__c;
			}else{
				isChangedOrNew = true;
			}
			if(o.Contract_Termination_Date__c < o.Contract_Start_Date__c && isChangedOrNew){
				o.addError(' The Lastest Campaign End Date must be on or after the Earliest Campaign Start Date. ');
			}
		}
		
	}
	
	private static void setPOIndexAccountFieldsValues(List<Opportunity> opps_insert, List<Opportunity> opps_update, Boolean isAfter){
		List<Opportunity> opps;
		if(!opps_insert.isEmpty()){
			opps = opps_insert;
		}else{
			opps = opps_update;
		}
		
		Map<ID, Integer> acctIds = new Map<ID, Integer>();
		
		for(Opportunity o : opps){
			if(o.AccountId != null){
				if(acctIds.containsKey(o.AccountId)){
					Integer temp = acctIds.get(o.AccountId);
					acctIds.put(o.AccountId, ++temp);
				}else{
					acctIds.put(o.AccountId, 1);
				}
			}
		}
		Map<ID, Account> accounts = new Map<ID, Account>([select Id, PO_Index__c, NASA_ID__c, AAS_Agency_Name__c, Master_Client__c, (select PO_Index__c from opportunities order by PO_Index__c asc) 
		                                                  from Account where Id IN: acctIds.keySet()]);
		if(!opps.isEmpty()){
			Map<ID, List<Integer>> index_counts = calculateIndexCounts(acctIds, accounts);
			for(Opportunity o : opps){
				if(accounts.containsKey(o.AccountId)){
					Account pAccount = accounts.get(o.AccountId);
					if(o.NPO_ID__c == null || o.AAS_Agency__c != pAccount.AAS_Agency_Name__c || o.AAS_Master_Client__c != pAccount.Master_Client__c){
						List<Integer> indexNums = index_counts.get(o.AccountId);
						o.PO_Index__c = indexNums[0];
						for(Integer i = 0 ; i < indexNums.size() - 1; i++){
							indexNums[i] = indexNums[i+1];
						}
						index_counts.put(o.AccountId, indexNums);
						String nasa_id = (pAccount.NASA_ID__c == null)? '' : pAccount.NASA_ID__c;
						o.NPO_ID__c = nasa_id + '-' + Math.round(o.PO_Index__c);
						o.AAS_Agency__c = pAccount.AAS_Agency_Name__c;
						o.AAS_Master_Client__c = pAccount.Master_Client__c;
					}
				}
			}
			if(isAfter && !opps_insert.isEmpty()){
				try{
					update opps;
				}catch(Exception ex){
                    GeneralConstants.mailAnyExceptionToMe('AASFieldUpdateHelperClass', 'update opps_insert in after insert Fail', ex);					
				}
			}
		}
	}
	
	private static Map<ID, List<Integer>> calculateIndexCounts(Map<ID, Integer> acctIds, Map<ID, Account> accounts){
			Map<ID, List<Integer>> index_counts = new Map<ID, List<Integer>>();
			for(ID aid : acctIds.keySet()){
				List<Integer> availableNum = new List<Integer>();
				Integer num_opps = acctIds.get(aid);
				Account a = accounts.get(aid);
				List<Opportunity> opps = a.opportunities;
				Map<Integer, Boolean> counts = new Map<Integer, Boolean>();
				for(Opportunity o : opps){
					if(o.PO_Index__c != null){
						counts.put(Math.round(o.PO_Index__c), true);
					}
				}
				for(Integer i = 1; num_opps > 0 ; i++){
					if(!counts.containsKey(i)){
						availableNum.add(i);
						num_opps--;
						counts.put(i, true);
					}
				}
				index_counts.put(aid, availableNum);
			}
			System.debug('index_counts = ' + index_counts);
			return index_counts;
	}
	
    //initialize Agency Accts' 12 Month Sold field : need to be removed after initialization finished
    public static void setAASAgencyAccountIdsInAgencyUpdate(List<Account> accts){
		for(Account a : accts){
			AASAgencyAccountIds.add(a.Id);
		}
		refresh_Agency_Acct_12_month_sold();
    }		
    
    /* Updated by Paul Lo Start */
    
    /* 
	   Ad-24230 AdWorks B-12, updated 10/12/11:
	   
	   1. Modify current Workflow that creates a new Task labelled "Task Submitted for Pre-Sales"
            i. Task Owner should be set to AAS Account Manager on the Quote
           ii. Keep existing notification email to AAS Account Manager (Email Alert, keep as is)
          iii. Change default Task name to "New Quote Requested (<Created Date of Task>): <Opportunity Name>"
	   
	   2. Modify current Workflow that creates a new Task labelled "Proposal Ready for Review"
            i. Task Owner should be set to Opportunity Owner of the Opportunity the Quote relates to
           ii. Keep existing notification email to AAS Account Manager (Email Alert, keep as is)
          iii. Change default Task name to "Quote Ready for Review (<Created Date of Task>): <Opportunity Name>"
	*/
	public static Boolean IsAASQuoteTaskCreated = false;
	public static void createAASQuoteTasksByStatus(Set<ID> quoteIds)
	{
		Set<ID> AASOppRecordTypeID = getOpportunityAASRecordTypeID();
		List<Task> tasksToInsert = new List<Task>();
		
		
		List<Quote> quoteAAs = [SELECT OpportunityId, Opportunity.Name, Opportunity.OwnerId, Status, Post_Sale_Manager__c FROM Quote
		                        WHERE Id IN :quoteIds AND Opportunity.RecordTypeId IN :AASOppRecordTypeID];

		if(!quoteAAs.isEmpty())
		{
			for(Quote q : quoteAAs)
			{			
			    /*  
			        existing settings for Task creation rule "Proposal Ready for Review" & "Task Submitted for Pre-Sales":
				    Due Date: Rule Trigger Date + 2 days
				    Priority: Normal
				    Status: Not Started
				    
				    Reminder is set to 8:00 AM on the due date
			    */
				Task newTask = new Task();
				newTask.WhatId = q.Id;
				newTask.ActivityDate = Date.today().addDays(2);
				newTask.Priority = 'Normal';
				newTask.Status = 'Not Started';
				newTask.IsReminderSet = true;
				newTask.ReminderDateTime = DateTime.newInstance(newTask.ActivityDate, Time.newInstance(8,0,0,0)); // reminder is 8:00 AM on due date
				
				String fmtQuoteDate = Date.today().format();
				
				/* 
				    since the trigger already organizes Opportunities by Quote Status, use Opportunity sets as flag to see what the Quote
				    Status is
				*/
				if(q.Status == RFP_Submitted)
				{
					newTask.OwnerId = q.Post_Sale_Manager__c;
					newTask.Subject = 'New Quote Requested (' + fmtQuoteDate + '): ' + q.Opportunity.Name;
				}
				else if(q.Status == Proposal_Submitted)
				{	
					newTask.OwnerId = q.Opportunity.OwnerId;
					newTask.Subject = 'Quote Ready for Review (' + fmtQuoteDate + '): ' + q.Opportunity.Name;
				}
				
				tasksToInsert.add(newTask);
			}
			
			insert tasksToInsert;
			
			IsAASQuoteTaskCreated = true;
		}
	}
}